<template>
  <div class="brand-car">
    <!-- 内容区 -->
    <div class="brand-car__body">
      <div class="letter-nav">
        <ul>
          <li
            v-for="(item, index) in letterArr"
            :key="index"
            :class="{ 'letter-li': index === letterIndex }"
            @click="onLetterLiClick(item, index)"
          >
            {{ item }}
          </li>
        </ul>
      </div>
      <div class="brand-cate">
        <a-checkbox
          :checked="isCheckAllOfProductList(data, -2)"
          @change="(event) => checkAllProductList(event, data, -1)"
        >
          全选
        </a-checkbox>
        <div v-for="item in data" :key="item.key" class="letter-car-cate">
          <div :class="`letter-car-${item.key}`">{{ item.name }}</div>
          <ul>
            <li
              v-for="product in item.products"
              :key="product.key"
              :class="{
                'active-li':
                  selectedItems[0] && selectedItems[0].key == product.key,
              }"
              @click="onLevalClick(product, product.key, 0)"
            >
              <span>{{ product.name }}</span>
              <a-badge
                :count="getSelectedCount(product)"
                :overflow-count="99999"
              />
            </li>
          </ul>
        </div>
      </div>
      <div class="car-cate">
        <ul v-if="productLists[0]">
          <li>
            <a-checkbox
              :checked="isCheckAllOfProductList(productLists[0], 0)"
              @change="
                (event) => checkAllProductList(event, productLists[0], 0)
              "
            >
              全选
            </a-checkbox>
          </li>
          <li
            v-for="product in productLists[0]"
            :key="product.key"
            :class="{
              'active-li':
                selectedItems[1] && selectedItems[1].key == product.key,
            }"
            @click="onLevalClick(product, product.key, 1)"
          >
            <span>{{ product.name }}</span>
            <a-badge
              :count="product.selectedKeys && product.selectedKeys.length"
              :overflow-count="99999"
            />
          </li>
        </ul>
        <div
          v-else
          style="
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  height: 100%;
                "
        >
          <span>请点击品牌来选择车型</span>
        </div>
      </div>
      <div v-if="productLists[0]" class="car-type-cate">
        <div v-if="productLists[1]">
          <ul>
            <li>
              <a-checkbox
                :checked="
                  selectedItems[1] &&
                    selectedItems[1].selectedKeys &&
                    selectedItems[1].selectedKeys.length ==
                      productLists[1].length
                "
                @click="selectAll(event, productLists[1], 1)"
              >
                全选
              </a-checkbox>
            </li>
            <li v-for="product in productLists[1]" :key="product.key">
              <a-checkbox
                :checked="
                  selectedItems[1].selectedKeys &&
                    selectedItems[1].selectedKeys.indexOf(product.key) > -1
                "
                @click="selectItem(product, product.key, 1)"
                >{{ product.name }}</a-checkbox
              >
            </li>
          </ul>
        </div>
        <div
          v-else
          style="
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  height: 100%;
                "
        >
          <span>请点击车型来选择型号</span>
        </div>
      </div>
    </div>
    <div
      v-if="
        allSelectedProducts && allSelectedProducts.length > 0 && modalVisible
      "
      style="z-index:9999;position:absolute;top:20px;width:1000px;border:1px solid #ddd;background:#fff;"
    >
      <div
        style="display:flex;align-items:center;justify-content:space-between;"
      >
        <span>查看已选车型</span>
        <a-button
          @click="
            () => {
              modalVisible = false;
            }
          "
          >关闭</a-button
        >
      </div>
      <a-table
        :columns="tableColums"
        :data-source="allSelectedProducts"
        :scroll="{ y: 300 }"
        :pagination="false"
        :show-header="false"
      >
        <span slot="action" slot-scope="text, record">
          <a-button
            size="small"
            @click="deleteFromAllSeletedProducts(record.preProduct, record.key)"
            >删除</a-button
          >
        </span>
      </a-table>
    </div>
  </div>
</template>

<script>
const brandData = [
  { brandId: "29", brandName: "东南", brandNatiName: "自主", letter: "D" },
  { brandId: "1965", brandName: "奔腾", brandNatiName: "自主", letter: "B" },
  { brandId: "1966", brandName: "奔腾2", brandNatiName: "自主", letter: "B" },
  { brandId: "30", brandName: "道奇", brandNatiName: "美系", letter: "D" },
];
export default {
  name: "BrandCarType",
  props: {
    levalCount: {
      type: Number,
      validator(value) {
        return value >= 3;
      },
      default() {
        return 3;
      },
    },
    dataLoader: {
      type: Function,
      default(product, key, leval, callback) {
        var products = [];
        //模拟查询数据
        for (let i = 0; i < 10; i++) {
          products.push({
            key: key + "-" + i,
            name: key + "-" + i,
          });
        }
        callback(products);
      },
    },
  },
  data() {
    return {
      visible: false,
      modalVisible: false,
      clicked: false,
      showClose: false,
      selectedLabel: "",
      letterIndex: -1,
      currentPlaceholder: "请选择品牌车型",
      brandData, // 请求的原始数据
      data: [
        {
          key: "B",
          name: "B",
          products: [
            {
              key: 1965,
              name: "奔腾",
              products: [],
            },
            {
              key: 1966,
              name: "奔腾1",
              products: [],
            },
          ],
        },
        {
          key: "D",
          name: "D",
          products: [
            {
              key: 3432,
              name: "东南",
              products: [],
            },
            {
              key: 1243,
              name: "道奇",
              products: [],
            },
          ],
        },
      ], // 原始数组改造后结构
      productLists: {}, // 保存每个leval的选中的记录
      selectedItems: {}, //保存当前leval选中的记录
    };
  },
  computed: {
    letterArr() {
      //字母数组
      return this.data.map((item) => item.key);
    },
    leval() {
      return this.levalCount - 2;
    },
    allSelectedProducts() {
      return this.getAllSeletedProducts();
    },
    tableColums() {
      var colums = [];
      if (this.allSelectedProducts && this.allSelectedProducts.length > 0)
        colums = Object.keys(this.allSelectedProducts[0]).map((k) => {
          /* if (k.indexOf("key") === -1) */
          return { dataIndex: k, key: k, title: k };
        });
      colums.push({
        title: "Action",
        key: "action",
        scopedSlots: { customRender: "action" },
      });
      return colums;
    },
  },
  methods: {
    dataSort(data) {
      return data.sort((val1, val) => {
        return val1.toUpperCase() > val.toUpperCase();
      });
    },
    // 点击input弹出popover
    handleClickChange(visible) {
      this.clicked = visible;
      this.showClose = visible;
    },
    // 点击字母事件
    onLetterLiClick(item, index) {
      this.letterIndex = index; // 当前选中字母颜色
      let currOffsetTop = document.getElementsByClassName(
        `letter-car-${item}`
      )[0].offsetTop;
      let country = document.getElementsByClassName("brand-cate")[0];
      country.scrollTop = currOffsetTop;
    },
    // 层级点击事件
    onLevalClick(product, key, leval) {
      //判断是否已经载入了数据，是则不重新载入
      if (!product.products || product.products.length == 0) {
        //this.$set(product, "products", []);
        //通过外部 loader 获取数据
        //leval+1 是为了方便调用者清楚对应的层级，但是实际上我们只处理  动态层级，即动态载入数据的 层级
        this.dataLoader(product, key, leval + 1, (productChildren) =>
          this.dataLoaderCallback(product, productChildren)
        );
      }
      this.$set(this.productLists, leval, product.products);
      //将当前载入的层级后面的层级的数据置空，不显示
      Object.keys(this.productLists).forEach((k) => {
        if (Number(k) > leval) {
          this.$set(this.productLists, Number(k), []);
          this.$set(this.selectedItems, Number(k), {});
        }
      });
      //设置当前层级的选中项为当前产品
      this.selectedItems[leval] = product;
    },
    /**最后一层级 选中取消*/
    selectItem(product, key, leval) {
      //判断所属的层级选中的项中的key 是否包含当前点击的 项，存在则移除，不存在则插入
      var index = this.selectedItems[leval].selectedKeys.indexOf(key);
      if (index > -1) {
        this.selectedItems[leval].selectedKeys.splice(index, 1);
        this.selectedItems[leval].selectedProducts.splice(index, 1);
      } else {
        this.selectedItems[leval].selectedKeys.push(key);
        this.selectedItems[leval].selectedProducts.push(product);
      }
    },
    /*选中所有：当前已选中部分，则清空，否则选中所有 （同时将选中的product记录是为了后面获取选中列表方便）*/
    selectAll(event, products, leval) {
      debugger; // eslint-disable-line
      this.$set(this.selectedItems[leval], "selectedKeys", []);
      this.$set(this.selectedItems[leval], "selectedProducts", []);

      if (event.target.checked) {
        products.forEach((product) => {
          this.selectedItems[leval].selectedKeys.push(product.key);
          this.selectedItems[leval].selectedProducts.push(product);
        });
      }
    },
    /*获取选中的总数  基于当前 product 后面的选中总数*/
    getSelectedCount(product) {
      // debugger // eslint-disable-line
      let _this = this;
      let count = 0;
      if (!product.products) return count;
      let products = product.products;

      //递归层次计算，主要遍历到最后一层判断 selectedKeys 的长度
      products.forEach((p) => {
        if (p.products && p.products.length > 0) {
          count += _this.getSelectedCount(p);
        }
        if (p.selectedKeys) count += p.selectedKeys.length;
      });
      return count;
    },
    /*获取选中的产品 递归（实际上最后一层 的 selectedProducts ） preproducts 为最后一层之前的每个层级的对象，*/
    getSeletedProducts(preproducts, product, productList) {
      let _this = this;

      if (product.selectedProducts && product.selectedProducts.length > 0) {
        product.selectedProducts.forEach((selectProduct) => {
          let productItem = {};
          //遍历之前层级的信息，
          for (let i = 0; i < preproducts.length; i++) {
            productItem["column_name_" + i] = preproducts[i].name;
            productItem["column_key_" + i] = preproducts[i].key;
          }

          productItem.key = selectProduct.key;
          productItem.name = selectProduct.name;
          productItem.preProduct = product;

          productList.push(productItem);
        });
      } else {
        if (product.products && product.products.length > 0) {
          var _preproducts = [].concat(preproducts);

          _preproducts.push(product);
          product.products.forEach((p) => {
            if (p.products && p.products.length > 0) {
              _this.getSeletedProducts(_preproducts, p, productList);
            }
          });
        }
      }
    },
    getAllSeletedProducts() {
      var products = [];
      this.data.forEach((product) => {
        this.getSeletedProducts([], product, products);
      });
      // debugger // eslint-disable-line
      return products;
    },
    // 选中所有
    isCheckAllOfProductList(products, leval) {
      if (!products) return false;
      for (let i = 0; i < products.length; i++) {
        var productItem = products[i];
        //递归统计
        if (!this.isCheckAllOfProduct(productItem, leval + 1)) return false;
      }
      return true;
    },
    // 选中所有
    checkAllProductList(event, products, leval) {
      //debugger // eslint-disable-line
      products.forEach((product) => {
        this.checkAllProductChildren(event, product, product.key, leval);
      });
    },
    // 选中产品的所有子项
    checkAllProductChildren(event, product, key, leval) {
      // 递归获取子项，取到最后一项时，将所有数据都选中或者取消选中
      // 判断是否已经载入了数据，是则不重新载入
      if (!product.products || product.products.length == 0) {
        //leval+1 实际上我们只处理 动态载入数据的 层级
        //通过外部 loader 获取数据
        this.dataLoader(product, key, leval + 1, (productChildren) => {
          this.dataLoaderCallback(product, productChildren); // 对请求的数据加入到点击项的product中
          this.getProductChildren(event, product, leval, productChildren); //对请求加入到product中的数据遍历，选中所有最后一项
        });
      } else this.getProductChildren(event, product, leval, product.products);
    },
    // 检查单个产品是否选中
    isCheckAllOfProduct(product, leval) {
      if (!product || !product.products) return false;
      // 递归产品列表判断是否全选
      if (this.leval == leval) {
        if (
          !(
            product.products &&
            product.selectedKeys &&
            product.selectedKeys.length > 0 &&
            product.products.length == product.selectedKeys.length
          )
        )
          return false;
      } else if (this.leval > leval) {
        if (product.products.length == 0) return false;
        for (let i = 0; i < product.products.length; i++) {
          var productItem = product.products[i];
          //倒数第二列，判断是否有子产品或者子产品是否都 选中了
          //递归统计
          if (!this.isCheckAllOfProduct(productItem, leval + 1)) return false;
        }
      }
      return true;
    },
    // 数据载入回调
    dataLoaderCallback(product, productChildren) {
      if (productChildren && productChildren instanceof Array) {
        productChildren.forEach((item) => {
          this.$set(item, "selectedProducts", []);
          this.$set(item, "selectedKeys", []);
        });
        this.$set(product, "products", productChildren);
      } else this.$set(product, "products", []);
    },
    getProductChildren(event, product, leval, children) {
      // 如果是 取最后一级，则选中
      if (this.leval == leval) {
        this.$set(product, "selectedKeys", []);
        this.$set(product, "selectedProducts", []);
        if (event.target.checked) {
          children.forEach((p) => {
            product.selectedKeys.push(p.key);
            product.selectedProducts.push(p);
          });
        }
      } else {
        children.forEach((p) => {
          this.checkAllProductChildren(event, p, p.key, leval + 1);
        });
      }
    },
    // 所有选中列表里删除选项
    deleteFromAllSeletedProducts(preProduct, key) {
      //借用选项的选中方法，重复选中将移除
      var index = preProduct.selectedKeys.indexOf(key);
      if (index > -1) {
        preProduct.selectedKeys.splice(index, 1);
        preProduct.selectedProducts.splice(index, 1);
      }
    }
  },
};
</script>

<style scoped lang="less">
@br: brand-car;
.@{br} {
  min-width: 500px;
  height: 100%;
  &__body {
    height: 375px;
    border-bottom: 1.6px solid #ecedf2;
    display: flex;
    .letter-nav {
      width: 44px;
      background: #f6f7fa;
      border-right: 1.6px solid #ecedf2;
      ul {
        display: flex;
        flex-direction: column;
        align-items: center;
        li {
          font-size: 15.62px;
          color: #9aa3b6;
          text-align: center;
          line-height: 28.12px;
          cursor: pointer;
        }
        .letter-li {
          color: #4f6ef2;
        }
      }
    }
    .brand-cate {
      width: 156px;
      overflow-y: auto;
      border-right: 1.6px solid #ecedf2;
      .letter-car-cate {
        div {
          background: #f6f7fa;
          height: 46.9px;
          line-height: 46.9px;
          padding-left: 17px;
        }
      }
    }
    .car-cate {
      min-width: 150px;
      flex: 1;
      overflow-y: auto;
      border-right: 1.6px solid #ecedf2;
    }
    .car-type-cate {
      width: 200px;
      overflow-y: auto;
    }
  }
  &__footer {
    height: 68.8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
}
.common-input /deep/ .ant-input {
  font-size: 14px;
}
.active-li {
  background: #ebf0ff;
}
.active-li span {
  color: #4f6ef2;
}
.car-cate ul li,
.brand-cate ul li,
.car-type-cate ul li {
  height: 46.9px;
  line-height: 46.9px;
  padding-left: 17px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
</style>
